package com.zhuhjay.eduservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhuhjay.commonutils.R;
import com.zhuhjay.eduservice.client.VodClient;
import com.zhuhjay.eduservice.entity.EduChapter;
import com.zhuhjay.eduservice.entity.EduCourse;
import com.zhuhjay.eduservice.entity.EduCourseDescription;
import com.zhuhjay.eduservice.entity.EduVideo;
import com.zhuhjay.eduservice.entity.frontvo.CourseWebVo;
import com.zhuhjay.eduservice.entity.vo.CourseInfoVo;
import com.zhuhjay.eduservice.entity.vo.CoursePublishVo;
import com.zhuhjay.eduservice.mapper.EduCourseMapper;
import com.zhuhjay.eduservice.service.EduChapterService;
import com.zhuhjay.eduservice.service.EduCourseDescriptionService;
import com.zhuhjay.eduservice.service.EduCourseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuhjay.eduservice.service.EduVideoService;
import com.zhuhjay.servicebase.exception.GuLiException;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author ZhuHJay
 * @since 2022-09-06
 */
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {

    @Resource
    private EduCourseDescriptionService courseDescriptionService;

    @Resource
    private EduVideoService videoService;

    @Resource
    private EduChapterService chapterService;

    @Resource
    private VodClient vodClient;

    @Override
    @Transactional(rollbackFor = GuLiException.class)
    @CachePut(value = "INDEX", key = "'COURSE'")
    public String saveCourseInfo(CourseInfoVo courseInfoVo) {
        // 添加课程信息到课程表中
        EduCourse course = new EduCourse();
        BeanUtils.copyProperties(courseInfoVo, course);
        if (!this.save(course)) {
            throw new GuLiException(20001, "添加课程失败");
        }
        // 添加课程描述到描述表中
        // 1 vs 1 关系，需要关联 id
        EduCourseDescription courseDescription = new EduCourseDescription()
                .setDescription(courseInfoVo.getDescription())
                .setId(course.getId());
        if (!courseDescriptionService.save(courseDescription)) {
            throw new GuLiException(20001, "添加课程描述失败");
        }
        return course.getId();
    }

    @Override
    public CourseInfoVo getCourseInfo(String courseId) {
        CourseInfoVo courseInfoVo = new CourseInfoVo();
        // 查询课程信息
        EduCourse course = this.getById(courseId);
        BeanUtils.copyProperties(course, courseInfoVo);
        // 查询课程描述
        EduCourseDescription courseDescription = courseDescriptionService.getById(courseId);
        courseInfoVo.setDescription(courseDescription.getDescription());
        return courseInfoVo;
    }

    @Override
    @Transactional(rollbackFor = GuLiException.class)
    @CacheEvict(value = "INDEX", key = "'COURSE'")
    public void updateCourseInfo(CourseInfoVo courseInfoVo) {
        // 修改课程信息
        EduCourse course = new EduCourse();
        BeanUtils.copyProperties(courseInfoVo, course);
        if (!this.updateById(course)) {
            throw new GuLiException(20001, "修改课程失败");
        }
        // 修改课程描述
        EduCourseDescription courseDescription = new EduCourseDescription()
                .setDescription(courseInfoVo.getDescription())
                .setId(course.getId());
        if (!courseDescriptionService.updateById(courseDescription)) {
            throw new GuLiException(20001, "修改课程描述失败");
        }
    }

    @Override
    public CoursePublishVo getPublishCourseInfo(String courseId) {
        return this.baseMapper.getCoursePublish(courseId);
    }

    @Override
    @Transactional(rollbackFor = GuLiException.class)
    @CacheEvict(value = "INDEX", key = "'COURSE'")
    public void deleteCourseById(String id) {
        // 按顺序删除，外键约束
        // 根据课程ID删除所有小节内容，还有删除视频
        List<EduVideo> videos = videoService.list(new LambdaQueryWrapper<EduVideo>()
                .eq(EduVideo::getCourseId, id));

        /* 一个一个删除 */
        for (EduVideo video : videos) {
            if (StringUtils.hasLength(video.getVideoSourceId())) {
                R result = vodClient.removeAlyVideo(video.getVideoSourceId());
                if (!result.getSuccess()) {
                    // 熔断器 DEBUG
                }
            }
            if (!videoService.removeById(video.getId())) {
                throw new GuLiException(20001, "小节信息删除失败");
            }
        }

        /* 批量删除
        List<String> videoSources = new ArrayList<>();
        for (EduVideo video : videos) {
            if (StringUtils.hasLength(video.getVideoSourceId())) {
                videoSources.add(video.getVideoSourceId());
            }
        }
        if (videoSources.size() > 0) {
            vodClient.removeAllAlyVideo(videoSources);
        }
        if (!videoService.remove(new LambdaQueryWrapper<EduVideo>()
                .eq(EduVideo::getCourseId, id))) {
            throw new GuLiException(20001, "小节信息删除失败");
        } */

        // 根据课程ID删除所有章节内容
        if (!chapterService.remove(new LambdaQueryWrapper<EduChapter>()
                .eq(EduChapter::getCourseId, id))) {
            throw new GuLiException(20001, "章节信息删除失败");
        }
        // 根据课程ID删除课程描述
        if (!courseDescriptionService.removeById(id)) {
            throw new GuLiException(20001, "课程描述信息删除失败");
        }
        // 删除课程信息
        if (!this.removeById(id)) {
            throw new GuLiException(20001, "课程信息删除失败");
        }
    }

    @Override
    @Cacheable(value = "COURSE", key = "'LIMIT 8'")
    public List<EduCourse> getCourseLimitList() {
        return this.list(new LambdaQueryWrapper<EduCourse>()
                .orderByDesc(EduCourse::getBuyCount).last("limit 8"));
    }

    @Override
    public CourseWebVo getFrontCourseInfo(String id) {
        return this.baseMapper.getCourseAllInfo(id);
    }
}
